import cmd from 'node-cmd'
import config from './config.js'

import print_log from './console.js'

// 可修改默认行为
let immediate = config?.immediate ?? true
// 默认不开启 debug 可在config中配置为true
let debug = config?.debug ?? false
// 需要保存时 运行的命令
const CommandList = config?.cmd ?? []

// 内部变量（保持默认 不能改动）
// 当前 进程pid字符串列表
let currentProcessList = []
// 当前是否完成关闭窗口
let isEndClose = true
// 追踪 进程的层级
let maxCloseProcessLevel = 3
// 追踪 进程的层级的临时变量
let currentMaxCloseProcessLevelTemp = 0

// 关闭命令的进程
const closeComandProcess = (pid = '') => {
    currentMaxCloseProcessLevelTemp += 1
    let run = cmd.runSync(`wmic process where (ParentProcessId=${pid.trim()}) get ProcessId`)
    if(debug) {
        console.log(`run.data：\n${run.data}\n currentMaxCloseProcessLevelTemp：${currentMaxCloseProcessLevelTemp}\n\n`)
        print_log()
    }
    // 如果 传入的pid没有其他子id的时候，先将其进行关闭
    if(run.data.trim() == '' || run.data.indexOf('没有') != -1 || run.data.indexOf('无效') != -1 || currentMaxCloseProcessLevelTemp > maxCloseProcessLevel) {
        // 重置临时变量
        currentMaxCloseProcessLevelTemp = 0
        let children_run = cmd.runSync(`taskkill /pid ${pid.trim()} /F`)
        if(children_run.err) {
            if(debug) {
                console.log(`children_run：${children_run.stderr}`)
                print_log()
            }
            return
        }
        return
    }
    let pid_str = run.data.split('ProcessId')[1].trim()
    let pids = pid_str.split('\n').filter((pid)=>{
        return pid.trim() != ''
    })
    // 如果 pids 的长度为1的时候，将其进行 回调
    if(pids.length < 2) { 
        closeComandProcess(pids[0].trim())
    }
    // 如果 pids 的长度大于1 则反过来进行遍历 在进入回调 
    pids.reverse().forEach((current_pid)=>{
        closeComandProcess(current_pid.trim())
    })
}

// 关闭 cmd 窗口和命令的进程
function closeCmd(current_pid) {
    isEndClose = false
    // 用于debug打印
    const processListTemp = currentProcessList
    try {
        // 调用关闭进程的方法
        if(debug) {
            console.log('调用关闭进程方法')
            print_log()
        }
        closeComandProcess(current_pid)
        if(debug) {
            console.log('关闭进程方法 执行完成')
            print_log()
        }
        // 关闭成功后，从pid列表中移除当前 current_pid
        currentProcessList = currentProcessList.filter((pid)=>{
            return pid != current_pid
        })
        if(debug) {
            console.log(`之前：[ ${processListTemp} ]\n现在：[ ${currentProcessList} ]\n成功关闭：${current_pid}`)
            print_log()
        }
        console.clear()
        isEndClose = true
    } catch(e) {
        if(debug) {
            console.log(e)
            print_log()
        } 
    }
}

import { watch } from './watch.js'

// 处理窗口关闭事件
function handleCmdWindowClose(current_pid) {
    if(currentProcessList.length != 0 && isEndClose) {
        isEndClose = false
        // 将当前的 pid 移除
        currentProcessList = currentProcessList.filter((pid)=>{
            return pid != current_pid
        })
        if(debug) {
            console.log(currentProcessList, current_pid)
            print_log()
        }
        currentProcessList.reverse().forEach((pid)=>{
            if(pid != current_pid) {
                closeCmd(pid)
            }
        })
        isEndClose = true
        console.clear()
        console.log('close')
    }
}

// 启动服务
const startReloadServer = ()=>{
    if(currentProcessList.length != 0 && isEndClose == true) {
        currentProcessList.forEach((pid)=>{
            closeCmd(pid)
        })
        if(!debug) {
            console.clear()
            console.log('prepare reload')
        }
    }
    setTimeout(()=>{
        if(isEndClose && currentProcessList.length == 0) {
            CommandList.forEach((cmdtext)=>{
                const run = cmd.run(cmdtext)
                currentProcessList.push(`${run.pid}`)
                run.on('close', ()=> {
                    handleCmdWindowClose(`${run.pid}`)
                })
            })
        }
        if(debug) {
            console.log(`\nisEndClose：${isEndClose}\n${currentProcessList}\n'opend'`)
            print_log()
        }
        if(!debug) console.log('reload success!')
    }, 1800)
}

// 是否在第一次运行的时候 就运行命令（可通过 将immediate 设置为 false 阻止第一次启动时 运行命令） 默认：true
if(immediate) {
    startReloadServer()
}

// 监听 整个项目中的文件保存和重命名的操作 如果进行了操作就执行 startReloadServer方法
watch(startReloadServer, 2000)